#include "util.hpp"
#include "log.hpp"

class ClientTcp
{
public:
    ClientTcp(const std::string &ip, uint16_t port)
        : ip_(ip), port_(port), socket_(-1)
    {
    }

    ~ClientTcp()
    {
        if (socket_ > 0)
            close(socket_);
    }

    void init()
    {
        socket_ = socket(AF_INET, SOCK_STREAM, 0);
        if (socket_ < 0)
        {
            std::cerr << "socket call failed : " << strerror(errno) << std::endl;
            exit(SOCKET_ERR);
        }
    }

    void start()
    {
        // connect，向服务器发起请求
        // 首先填充需要连接的远端主机的基本信息
        struct sockaddr_in server;
        bzero(&server, sizeof server);
        server.sin_family = AF_INET;
        server.sin_port = htons(port_);
        inet_aton(ip_.c_str(), &server.sin_addr);

        // 发送连接请求，connect会自动帮我们进行bind
        if (connect(socket_, (const sockaddr *)&server, sizeof(server)) != 0)
        {
            std::cerr << "connect call failed : " << strerror(errno) << std::endl;
            exit(CONN_ERR);
        }
        std::cout << "connect success!!!" << std::endl;
    }

    void trans()
    {
        std::string message;
        while (true)
        {
            message.clear();
            std::cout << "Please Enter# ";
            std::getline(std::cin, message);

            ssize_t s = write(socket_, message.c_str(), message.size());
            if (s > 0)
            {
                message.resize(1024);
                ssize_t s = read(socket_, (char *)(message.c_str()), 1024);
                if (s > 0)
                    message[s] = '\0';
                std::cout << "Server Echo# " << message << std::endl;
            }
            else
                break;
        }
    }

private:
    int socket_;
    std::string ip_;
    uint16_t port_;
};

static void Usage(std::string proc)
{
    std::cerr << "Usage:\n\t" << proc << " prot ip" << std::endl;
    std::cerr << "Example:\n\t" << proc << " 127.0.0.1 8080\n"
              << std::endl;
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t serverPort = atoi(argv[2]);
    std::string serverIp = argv[1];

    ClientTcp client(serverIp, serverPort);
    client.init();
    client.start();
    client.trans();
    return 0;
}